home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Utilities / pLayer 1.0d5 / pLayer Source / pLayerUnit.p < prev    next >
Encoding:
Text File  |  1993-06-18  |  33.3 KB  |  1,172 lines  |  [TEXT/MPS ]

  1. {
  2.     $Workfile:   pLayerComp.p  $
  3.     $Revision:   1.0  $
  4.  
  5.     This handles all of our pallette stuff.  Separated from pLayer.p for clarity.
  6.  
  7.     © 1993 CE Software, Inc.  All rights reserved.
  8.  
  9.     WHEN    WHO        WHAT
  10.  
  11. •••••
  12.     
  13. •••••
  14. }
  15.  
  16. UNIT pLayerUnit;
  17.  
  18. INTERFACE
  19.  
  20. USES Memtypes, Quickdraw, OSIntf, ToolIntf, PackIntf, MacPrint, GestaltEqu, Folders,
  21.     Errors, Notification, Processes, Aliases, TextServices, AppleEvents;
  22.  
  23. Function InitLayer:OSErr;
  24. Procedure CloseLayer;
  25. Procedure LayerIdleProc(var doneflag:boolean);
  26. Function myGNEFilter (result:integer; var event:EventRecord):integer;
  27.  
  28. Procedure HandleNew;
  29. Procedure HandleOpen;
  30. Procedure HandleSave;
  31. Procedure DoOpenFile(TheSpec:FSSpec);
  32. Procedure DoOpenApp(AllowUserInteraction:Boolean);
  33.  
  34. IMPLEMENTATION
  35.  
  36. {$D+} {$R-}
  37.  
  38. CONST
  39.     kClosePallette=-1;
  40.     kZoomPallette=-2;
  41.     
  42.     HiliteMode = $938; {[GLOBAL VAR]  used for color highlighting}
  43.     
  44.     MyItemWidth=48;
  45.     MyItemHeight=80;
  46.     MaxNumberIcons=12;
  47.  
  48. TYPE
  49.     MyGlobals=record
  50.         StoredPalletteWindow:windowptr;            {MUST start our globals (TSMHelper assumes this}
  51.         MyProcess:        ProcessSerialNumber;
  52.         WhatToDo:        integer;                {Message to do stuff}
  53.         PalletteIcons:    integer;
  54.         PalletteVref:    integer;
  55.         PalletteDirID:    longint;
  56.         PalletteName:    str63;
  57.         PalletteDTMan:    integer;
  58.         IAmZoomed:        Boolean;
  59.         BottomLeft:        point;
  60.         TheName:        array[1..MaxNumberIcons] of str31; {Names of icons in folder}
  61.         TempIcon:        packed array[1..kLarge8BitIconSize] of char;
  62.         end;
  63.     MyGlobalsPtr=^MyGlobals;
  64.  
  65. Function Storage:MyGlobalsPtr; external;
  66.     {This routine holds some data within our data, so we don't have to worry about A5}
  67. Procedure HookUp; external;
  68.     {This connects our jGNE Event filter, necessary so that we can grab the events for our windoid}
  69. Procedure UnHook; external;
  70.     {This unconnects our jGNE Event filter, so that we can quit cleanly.}
  71.  
  72. {--------------------------------------------------------------------------
  73.     
  74.     TellFinderOpen
  75.         A simple routine that sends an AppleEvent to the Finder to launch a file.  Since
  76.         the Finder does all the work, we don't have to distinguish between cdevs, desk accessories,
  77.         data files, or applications.
  78.     
  79.         Not part of the layer stuff, just the "engine" that makes things work.
  80.  
  81.  --------------------------------------------------------------------------}
  82. Function TellFinderOpen(name:str63; Thevref:integer; TheDir:longint):OSErr;
  83. var    message, reply: AppleEvent ;
  84.     targetAddress: AEAddressDesc ;
  85.     listElem: AEDesc ;
  86.     resultList: AEDescList ;
  87.     TheSpec:FSSpec;
  88.     TheCreator:OSType;
  89.         
  90.     Procedure FailErr(io:OSErr);
  91.     begin
  92.         if io<>NoErr then begin
  93.             TellFinderOpen:=io;
  94.             exit(TellFinderOpen);
  95.             end;
  96.         end;
  97.     
  98. begin
  99.     TellFinderOpen:=NoErr;
  100.     
  101.     {Address the AppleEvent}
  102.     TheCreator:='MACS';
  103.     FailErr(AECreateDesc(typeApplSignature,@TheCreator,sizeof(TheCreator),targetAddress));
  104.     
  105.     FailErr( AECreateAppleEvent( 'FNDR', 'sope', targetAddress, 0, 0, message ) ) ;
  106.     
  107.     {Create the parameters}
  108.     
  109.     FailErr( AECreateList( nil, 0, false, resultList ) ) ;
  110.     FailErr(FSMakeFSSpec(TheVref, thedir, name, TheSpec));
  111.     FailErr(NewAliasMinimal(TheSpec,aliashandle(listElem.dataHandle)));
  112.     listElem.descriptorType:=typeAlias;
  113.     FailErr(AEPutDesc(resultList, 1, listElem));
  114.     FailErr(AEDisposeDesc( listElem ) ) ;
  115.     FailErr( AEPutParamDesc( message, 'fsel', resultList ) ) ;
  116.     FailErr( AEDisposeDesc( resultList ) ) ;
  117.         
  118.     FailErr(FSMakeFSSpec(TheVref, thedir, '', TheSpec));
  119.     FailErr(NewAliasMinimal(TheSpec,aliashandle(listElem.dataHandle)));
  120.     listElem.descriptorType:=typeAlias;
  121.     FailErr( AEPutParamDesc( message, '----', listElem ) ) ;
  122.     FailErr( AEDisposeDesc( listElem ) ) ;
  123.     
  124.     {Set up the reply, except we don't really want one}
  125.     reply.dataHandle := nil ;
  126.     
  127.     FailErr( AESend( message, reply, kAENoReply + kAENeverInteract, kAENormalPriority, 1000, nil, nil ) ) ;
  128.     
  129.     FailErr( AEDisposeDesc( message ) ) ;        { we own message and reply, and must dispose oftthem }
  130.     FailErr( AEDisposeDesc( targetAddress ) ) ;
  131.     end;
  132.  
  133. {--------------------------------------------------------------------------
  134.     
  135.     GetPrefsFileSpec
  136.     
  137.         Returns an FSSpec of the preferences folder
  138.  
  139.  --------------------------------------------------------------------------}
  140. Procedure GetPrefsFileSpec(var TheSpec:FSSpec);
  141. var    io:OSErr;
  142. begin
  143.     with TheSpec do begin
  144.         io:=FindFolder(kOnSystemDisk,kPreferencesFolderType,true,vRefNum,parID);
  145.         name:='pLayer.Prefs';
  146.         end;
  147.     end;
  148.  
  149. {--------------------------------------------------------------------------
  150.     
  151.     SaveThePallette
  152.     
  153.         Given an FSSpec, create a data file of the current spec
  154.  
  155.  --------------------------------------------------------------------------}
  156. Function SaveThePallette(TheSpec:FSSpec):OSErr;
  157. var    refnum:integer;
  158.     PalletteSpec:FSSpec;
  159.     TempAlias:AliasHandle;
  160.     h:handle;
  161.     
  162.     Procedure FailErr(io:OSErr);
  163.     begin
  164.         if io<>NoErr then begin
  165.             SaveThePallette:=io;
  166.             if refnum<>0 then CloseResFile(refnum);
  167.             exit(SaveThePallette);
  168.             end;
  169.         end;
  170.     
  171. begin
  172.     refnum:=0;
  173.     with storage^ do
  174.         FailErr(FSMakeFSSpec(PalletteVref,PalletteDirID, '', PalletteSpec));
  175.     FailErr(NewAlias(nil,PalletteSpec,TempAlias));
  176.     
  177.     FSpCreateResFile(TheSpec,'pLay','pall',0);
  178.     refnum:=FSpOpenResFile(TheSpec,0);
  179.     if refnum=-1 then FailErr(-100); {oops, can't save file}
  180.     h:=Get1Resource('alis',0);
  181.     if h<>nil then begin
  182.         RmveResource(h);
  183.         disposhandle(h);
  184.         CloseResFile(refnum);
  185.         refnum:=FSpOpenResFile(TheSpec,0);
  186.         end;
  187.     AddResource(handle(TempAlias),'alis',0,storage^.PalletteName);
  188.     WriteResource(handle(TempAlias));
  189.     
  190.     h:=Get1Resource('BLft',0);
  191.     if h=nil then begin
  192.         h:=NewHandle(4);
  193.         AddResource(h,'BLft',0,'BottomLeft');
  194.         WriteResource(h);
  195.         end;
  196.     with storage^ do
  197.         BlockMove(@BottomLeft,h^,4);
  198.     ChangedResource(h);
  199.     WriteResource(h);
  200.     CloseResFile(refnum);
  201.     SaveThePallette:=NoErr;
  202.     end;
  203.  
  204. {--------------------------------------------------------------------------
  205.     
  206.     SavePrefs
  207.     
  208.         Itsy-bits routine to save the current setting as the preferences
  209.  
  210.  --------------------------------------------------------------------------}
  211. Procedure SavePrefs;
  212. var    TempSpec:FSSpec;
  213.     io:OSErr;
  214. begin
  215.     GetPrefsFileSpec(TempSpec);
  216.     io:=SaveThePallette(TempSpec);
  217.     end;
  218. {--------------------------------------------------------------------------
  219.     
  220.     ReadThePallette
  221.     
  222.         Given an FSSpec, get the FSSpec from within it
  223.  
  224.  --------------------------------------------------------------------------}
  225. Function ReadThePallette(var TheSpec:FSSpec):OSErr;
  226. var    refnum:integer;
  227.     WasChanged:boolean;
  228.     TempAlias:AliasHandle;
  229.     h:handle;
  230.     TempPoint:point;
  231.     
  232.     Procedure FailErr(io:OSErr);
  233.     begin
  234.         if io<>NoErr then begin
  235.             ReadThePallette:=io;
  236.             if refnum<>0 then CloseResFile(refnum);
  237.             exit(ReadThePallette);
  238.             end;
  239.         end;
  240.     
  241. begin
  242.     refnum:=0;
  243.     refnum:=FSpOpenResFile(TheSpec,0);
  244.     if refnum=-1 then FailErr(-100); {oops, can't open file}
  245.     TempAlias:=pointer(Get1Resource('alis',0));
  246.     if TempAlias<>nil then FailErr(ResolveAlias(nil,TempAlias,TheSpec,WasChanged))
  247.         else FailErr(-101); {No alias resource}
  248.     h:=Get1Resource('BLft',0);
  249.     if h<>nil then begin
  250.         Blockmove(h^,@TempPoint,4);
  251.         if PtInRgn(TempPoint,GetGrayRgn) then {only update bottom left if on screen}
  252.             storage^.BottomLeft:=TempPoint;
  253.         end;
  254.     CloseResFile(refnum);
  255.     ReadThePallette:=NoErr;
  256.     end;
  257.  
  258. {--------------------------------------------------------------------------
  259.     
  260.     SilentResolveAliasFile
  261.     
  262.         A replacement for ResolveAliasFile that won't attempt to go to other
  263.         volumes.
  264.  
  265.  --------------------------------------------------------------------------}
  266. FUNCTION SilentResolveAliasFile(VAR theSpec: FSSpec;
  267.                           resolveAliasChains: BOOLEAN;
  268.                           VAR targetIsFolder: BOOLEAN;
  269.                           VAR wasAliased: BOOLEAN): OSErr;
  270. var    refnum:        integer;
  271.     WasChanged:    boolean;
  272.     TempAlias:    AliasHandle;
  273.     fndrInfo:    FInfo;
  274.     theCount:    integer;
  275.     myCPB:        CInfoPBRec;
  276.     s2:            str255;
  277.     io:            OSErr;
  278.     
  279.     Procedure FailErr(io:OSErr);
  280.     begin
  281.         if io<>NoErr then begin
  282.             SilentResolveAliasFile:=io;
  283.             if refnum<>0 then CloseResFile(refnum);
  284.             exit(SilentResolveAliasFile);
  285.             end;
  286.         end;
  287.     
  288. begin
  289.     refnum:=0;
  290.     SilentResolveAliasFile:=NoErr;
  291.     targetIsFolder:=false;
  292.     wasAliased:=false;
  293.     FailErr(FSpGetFInfo(TheSpec,fndrInfo));
  294.     if bitand(fndrInfo.fdflags,$00008000)=0 then exit(SilentResolveAliasFile); {Not an alias file}
  295.     
  296.     wasAliased:=true;
  297.     refnum:=FSpOpenResFile(TheSpec,0);
  298.     if refnum=-1 then FailErr(-100); {oops, can't open file}
  299.     TempAlias:=pointer(Get1Resource('alis',0));
  300.     if TempAlias=nil then FailErr(-101); {No alias resource}
  301.  
  302.     thecount:=1;
  303.     io:=(MatchAlias(nil,kArmSearch+kARMNoUI,
  304.             TempAlias,thecount,@TheSpec,WasChanged,nil,nil));
  305.     FailErr(io);
  306.     
  307.     if TheSpec.ParID=1 then targetIsFolder:=true {this is a volume!}
  308.         else
  309.         with mycpb do begin {is this a directory?}
  310.             ioNamePtr:=@s2; s2:=TheSpec.name;
  311.             iovrefnum:=TheSpec.vrefnum;
  312.             ioDrDirID:=TheSpec.ParID;
  313.             ioFDirIndex:=0;
  314.             FailErr(PBGetCatInfo(@mycpb,false));
  315.             targetIsFolder:=(BitTst(@ioFlAttrib,3));
  316.             end;
  317.     CloseResFile(refnum);
  318.     end;
  319.  
  320. {--------------------------------------------------------------------------
  321.     
  322.     GetAFolder
  323.     
  324.         Some simple CustomGetFile hacking to select a folder.
  325.  
  326.  --------------------------------------------------------------------------}
  327. var
  328.     MyTempReply:StandardFileReply;
  329.     MyLastName:str31;
  330.  
  331. Function MyDlgHook(item:integer; theDialog:DialogPtr; p:ptr):integer;
  332. VAR  dtype:integer; ditem:handle;dbox:rect;
  333.      s,s2:str255;
  334.      io:OSErr;
  335.      
  336. Begin
  337.     if ResType(WindowPeek(TheDialog)^.refCon)<>'stdf' then begin
  338.         MyDlgHook:=item;
  339.         exit(MyDlgHook);
  340.         end;
  341.     if (item=sfHookFirstCall) then MyLastName:='';
  342.     
  343.     if MyLastName<>MyTempReply.sfFile.name then begin
  344.         {update the button}
  345.         GetIndString(s,1000,1);
  346.         GetDItem(TheDialog,10,dtype,ditem,dbox);
  347.         if MyTempReply.sfFile.name<>'' then begin
  348.             s:=concat(s,'"',MyTempReply.sfFile.name,'"');
  349.             HiliteControl(controlhandle(ditem),0);
  350.             SetCTitle(controlhandle(ditem),s);
  351.             end
  352.             else begin
  353.                 GetIndString(s2,1000,2);
  354.                 s:=concat(s,s2);
  355.                 HiliteControl(controlhandle(ditem),255);
  356.                 SetCTitle(controlhandle(ditem),s);
  357.                 end;
  358.         MyLastName:=MyTempReply.sfFile.name;
  359.         end;
  360.     
  361.     if item=10 then item:=1;
  362.     MyDlgHook:=item;
  363.     end;
  364.  
  365. FUNCTION  AddFileFilter(PB: CInfoPBPtr; p:ptr): BOOLEAN;
  366. var i:integer; flag:boolean;
  367.  
  368. Begin
  369.     with pB^ do
  370.        if  BitTst(@pb^.ioFLAttrib,3) then AddFileFilter:=false
  371.       else AddFileFilter:=true;
  372.   end;
  373.   
  374. Function GetAFolder(VAR thespec:FSSpec):boolean;
  375. VAR where:point; i,i2,count:integer; MyFile2:SFTypeList; targetIsFolder, wasAliased:boolean;
  376.  
  377. begin
  378.     GetAFolder:=false;
  379.     where.h:=-1; where.v:=-1;
  380.     MyTempReply.sfFile.name:='';
  381.         
  382.     CustomGetFile(@AddFileFilter,-1,MyFile2,MyTempReply,1000,where,@MyDlgHook,nil,nil,nil,nil);
  383.         
  384.     GetAFolder:=MyTempReply.sfgood;
  385.     if MyTempReply.sfgood then begin
  386.         thespec:=MyTempReply.sfFile;
  387.         if ResolveAliasFile(theSpec, true, targetIsFolder, wasAliased)=NoErr then
  388.             if not targetIsFolder then GetAFolder:=false;
  389.         end;
  390.     end;
  391.  
  392. {--------------------------------------------------------------------------
  393.     
  394.     Some color grapics utilities, to draw pretty stuff.
  395.     
  396.     PlotColorPtr
  397.         A simple routine to draw a color icon.
  398.     PlotBWPtr
  399.         A simple routine to draw a black and white icon (not using any color QuickDraw calls)
  400.     ColorRectDepth
  401.         Gets the "depth" of the rectangle, to know whether to plot color or B&W
  402.     
  403.         Not part of the layer stuff, used by our UpdateEvent handler.
  404.  
  405.  --------------------------------------------------------------------------}
  406. Procedure PlotColorPtr(wDepth,wFaceSize:integer; DestRect : Rect; p:ptr; themode:integer);
  407. type bitmapPtr=^bitmap;
  408. var hPixMap:PixMapHandle; pCurPort:grafptr;
  409. begin
  410.     
  411.     hPixMap:=NewPixMap;
  412.     MoveHHi(handle(hPixMap));
  413.     HLock(handle(hPixMap));
  414.     
  415.     with hPixMap^^ do begin
  416.         hRes:=$480000;
  417.         vRes:=$480000;
  418.         pixelType:=0;
  419.         planeBytes:=0;
  420.         bounds.top:=0;
  421.         bounds.left:=0;
  422.         bounds.bottom:=wFaceSize;
  423.         bounds.right:=wFaceSize;
  424.         pixelSize:=wDepth;
  425.         cmpCount:=wDepth;
  426.         rowBytes:=((wDepth*wFaceSize) div 8)+$8000;
  427.         baseAddr:=pointer(p);
  428.         end;
  429.     
  430.     DisposCTable(hPixMap^^.pmTable);
  431.     hPixMap^^.pmTable:=GetCTable(wDepth);
  432.     
  433.     GetPort(pCurPort);
  434.     CopyBits(bitmapPtr(hPixMap^)^, pCurPort^.portbits, hPixMap^^.bounds,
  435.         DestRect,themode,nil);
  436.     hPixMap^^.baseaddr:=nil;
  437.     hunlock(handle(hPixMap));
  438.     disposPixMap(hPixMap);
  439.     end;
  440.  
  441. Procedure PlotBWPtr(wFaceSize:integer; DestRect : Rect; p:ptr);
  442. var pCurPort:grafptr; mybitmap:bitmap;
  443. begin
  444.     with mybitmap do begin
  445.         bounds.top:=0;
  446.         bounds.left:=0;
  447.         bounds.bottom:=wFaceSize;
  448.         bounds.right:=wFaceSize;
  449.         rowBytes:=wFaceSize div 8;
  450.         baseAddr:=pointer(p);
  451.         end;
  452.     GetPort(pCurPort);
  453.     CopyBits(mybitmap, pCurPort^.portbits, mybitmap.bounds,DestRect,0,nil);
  454.     end;
  455.  
  456. Function ColorRectDepth(therect:rect):integer;
  457. var    response: LONGINT; r2:rect; thegd:GDHandle;
  458. begin
  459.     ColorRectDepth:=1;
  460.     if gestalt(gestaltQuickdrawVersion,response)=noerr then
  461.       if response>=gestalt8BitQD then begin {determine if we can use the color QD calls}
  462.         r2:=therect;
  463.         LocalToGlobal(r2.topleft);
  464.         LocalToGlobal(r2.botright);
  465.         thegd:=GetMaxDevice(r2);
  466.         if thegd<>nil then
  467.           ColorRectDepth:=thegd^^.gdPMap^^.pixelSize;
  468.         end;
  469.     end;
  470.  
  471. {--------------------------------------------------------------------------
  472.     
  473.     FSDTManRefNum
  474.         Utility routine to get the refnum used by the DeskTop Manager
  475.     
  476.         Not part of the layer stuff, used by our UpdateEvent handler.
  477.  
  478.  --------------------------------------------------------------------------}
  479. Function FSDTManRefNum(thevref:integer):integer;
  480. var    myDTPB:    DTPBRec;
  481.     io:OSErr;
  482. begin
  483.     myDTPB.ioNamePtr:=nil;
  484.     myDTPB.ioVRefNum:=thevref;
  485.     io:=PBDTGetPath(@myDTPB);
  486.     if io=NoErr then FSDTManRefNum:=myDTPB.ioDTRefnum
  487.         else FSDTManRefNum:=0;
  488.     end;
  489.  
  490. {--------------------------------------------------------------------------
  491.     
  492.     PlotFileIcon
  493.         Gets appropriate icon for a file (from custom icon if present, or DeskTop Manager
  494.         if no custom icon) and plots it.
  495.     
  496.         Not part of the layer stuff, used by our UpdateEvent handler.
  497.  
  498.  --------------------------------------------------------------------------}
  499. Procedure PlotFileIcon(thename:str63; thevref:integer; thedir:longint; therect:rect);
  500. var    TheSpec:FSSpec;
  501.     fndrInfo: FInfo;
  502.     
  503.     Procedure HandleCustomIcon;
  504.     var    refnum:integer; h:handle;
  505.         Procedure TryBAndW;
  506.         begin
  507.             h:=Get1Resource('ICN#',-16455);
  508.             if h<>nil then begin
  509.                 hlock(h);
  510.                 PlotBWPtr(32,therect,pointer(h^));
  511.                 end;
  512.             end;
  513.         Procedure TryColor;
  514.         begin
  515.             h:=Get1Resource('icl8',-16455);
  516.             if h=nil then TryBAndW
  517.                 else begin
  518.                     hlock(h);
  519.                     PlotColorPtr(8,32,therect,pointer(h^),0);
  520.                     end;
  521.             end;
  522.         
  523.     begin
  524.         refnum:=FSpOpenResFile(TheSpec,0);
  525.         if refnum<>-1 then begin
  526.             if ColorRectDepth(therect)>2 then TryColor else TryBAndW;
  527.             CloseResFile(refnum);
  528.             if h<>nil then exit(PlotFileIcon);
  529.             end;
  530.         end;
  531.  
  532.     Procedure HandleSpecialIcon(whichicon:integer);
  533.     var    h:handle;
  534.         Procedure TryBAndWSpecial;
  535.         begin
  536.             h:=GetResource('ICN#',whichicon);  {Get the icon to the folder out of the system file}
  537.             if h<>nil then begin
  538.                 hlock(h);
  539.                 PlotBWPtr(32,therect,pointer(h^));
  540.                 hunlock(h);
  541.                 end;
  542.             end;
  543.         Procedure TryColorSpecial;
  544.         begin
  545.             h:=GetResource('icl8',whichicon);  {Get the icon to the folder out of the system file}
  546.             if h<>nil then begin
  547.                 hlock(h);
  548.                 PlotColorPtr(8,32,therect,pointer(h^),0);
  549.                 hunlock(h);
  550.                 end
  551.                 else TryBAndWSpecial;
  552.             end;
  553.     begin
  554.         if ColorRectDepth(therect)>2 then TryColorSpecial else TryBAndWSpecial;
  555.         exit(PlotFileIcon);
  556.         end;
  557.     
  558.     Procedure HandleSpecialAlias;
  559.     var    targetIsFolder, wasAliased:boolean;
  560.     begin
  561.         targetIsFolder:=false;
  562.         if SilentResolveAliasFile(theSpec, true, targetIsFolder, wasAliased)=NoErr then begin
  563.             if not targetIsFolder then begin
  564.                 if FSpGetFInfo(TheSpec,fndrInfo)<>NoErr then exit(PlotFileIcon);
  565.                 if bitand(fndrInfo.fdFlags,1024)<>0 then HandleCustomIcon; {target has a custom icon}
  566.                 exit(handleSpecialAlias);
  567.                 end;
  568.             {We've got a folder or volume here, do something clever with it!}
  569.             TheSpec.name:=concat(TheSpec.name,':Icon_');
  570.             TheSpec.name[length(TheSpec.name)]:=chr(13);
  571.             HandleCustomIcon; {try to open and draw the special icon!}
  572.             end;
  573.         {Check for various special folder types}
  574.         if fndrInfo.fdtype='faam' then HandleSpecialIcon(-3982)
  575.             else if fndrInfo.fdtype='fadr' then HandleSpecialIcon(-3979)
  576.             else if fndrInfo.fdtype='fact' then HandleSpecialIcon(-3976)
  577.             else if fndrInfo.fdtype='faet' then HandleSpecialIcon(-3978)
  578.             else if fndrInfo.fdtype='faex' then HandleSpecialIcon(-3973)
  579.             else if fndrInfo.fdtype='famn' then HandleSpecialIcon(-3978)
  580.             else if fndrInfo.fdtype='fapf' then HandleSpecialIcon(-3974)
  581.             else if fndrInfo.fdtype='fapn' then HandleSpecialIcon(-3975)
  582.             else if fndrInfo.fdtype='fash' then HandleSpecialIcon(-3978)
  583.             else if fndrInfo.fdtype='fast' then HandleSpecialIcon(-3981)
  584.             else if fndrInfo.fdtype='fasy' then HandleSpecialIcon(-3983)
  585.             else if fndrInfo.fdtype='trsh' then HandleSpecialIcon(-3993)
  586.             else if fndrInfo.fdtype='fdrp' then HandleSpecialIcon(-3999)
  587.             else if fndrInfo.fdtype='srvr' then HandleSpecialIcon(-3978)
  588.             else if fndrInfo.fdtype='flpy' then HandleSpecialIcon(-3998)
  589.             else if fndrInfo.fdtype='hdsk' then HandleSpecialIcon(-3998)
  590.             else if targetIsFolder then HandleSpecialIcon(-3999);
  591.         end;
  592.     
  593.     Procedure HandleDTMan;
  594.     var    myDTPB:    DTPBRec;
  595.         io:OSErr;
  596.         
  597.         Procedure TryBAndWDT;
  598.         begin
  599.             myDTPB.ioDTReqCount:=kLargeIconSize;
  600.             myDTPB.ioIconType:=kLargeIcon;
  601.             io:=PBDTGetIcon(@myDTPB,false);
  602.             if io=NoErr then begin
  603.                 with storage^ do
  604.                     PlotBWPtr(32,therect,@TempIcon);
  605.                 exit(PlotFileIcon);
  606.                 end;
  607.             end;
  608.         
  609.         Procedure TryColorDT;
  610.         begin
  611.             myDTPB.ioDTReqCount:=kLarge8BitIconSize;
  612.             myDTPB.ioIconType:=kLarge8BitIcon;
  613.             io:=PBDTGetIcon(@myDTPB,false);
  614.             if io=NoErr then begin
  615.                 with storage^ do
  616.                     PlotColorPtr(8,32,therect,@TempIcon,0);
  617.                 exit(PlotFileIcon);
  618.                 end
  619.                 else TryBAndWDT;
  620.             end;
  621.         
  622.         Procedure TryMultiple;
  623.         var    vindex,tempref:integer;
  624.             mypb:paramBlockRec;
  625.             vname:str63;
  626.             io:OSErr;
  627.         begin
  628.             vindex:=1;
  629.                 repeat
  630.                 with mypb do begin
  631.                     ioCompletion:=NIL;
  632.                     ioNameptr:=@vname;
  633.                     ioVRefNum:=0;
  634.                     ioVolIndex:=vindex;
  635.                     end;
  636.                 io:=PBGetVInfo(@mypb,false);
  637.                 if io=NoErr then begin
  638.                     tempref:=FSDTManRefNum(mypb.iovrefnum);
  639.                     if tempref<>0 then begin
  640.                         with storage^,myDTPB do begin
  641.                             ioDTRefNum:=tempref;
  642.                             ioTagInfo:=0;
  643.                             ioDTBuffer:=@TempIcon;
  644.                             ioFileCreator:=fndrInfo.fdCreator;
  645.                             ioFileType:=fndrInfo.fdType;
  646.                             end;
  647.                         if ColorRectDepth(therect)>2 then TryColorDT else TryBAndWDT;
  648.                         end;
  649.                     end;
  650.                 vindex:=vindex+1;
  651.                 until io<>NoErr;
  652.             end;
  653.  
  654.     begin
  655.         with storage^,myDTPB do begin
  656.             ioDTRefNum:=PalletteDTMan;
  657.             ioTagInfo:=0;
  658.             ioDTBuffer:=@TempIcon;
  659.             ioFileCreator:=fndrInfo.fdCreator;
  660.             ioFileType:=fndrInfo.fdType;
  661.             end;
  662.         if ColorRectDepth(therect)>2 then TryColorDT else TryBAndWDT;
  663.         TryMultiple;
  664.         end;
  665.     
  666. begin
  667.     with therect do begin
  668.         bottom:=top+32;
  669.         left:=(left+right-32) div 2;
  670.         right:=left+32;
  671.         end;
  672.     framerect(therect);
  673.             
  674.     TheSpec.name:=thename;
  675.     TheSpec.Vrefnum:=thevref;
  676.     TheSpec.ParID:=thedir;
  677.     if FSpGetFInfo(TheSpec,fndrInfo)=NoErr then begin
  678.         if bitand(fndrInfo.fdFlags,1024)<>0 then HandleCustomIcon; {the file itself has a custom icon}
  679.         if bitand(fndrInfo.fdFlags,$00080000)<>0 then HandleSpecialAlias;
  680.         end;
  681.     
  682.     HandleDTMan;
  683.     
  684.     if fndrInfo.fdType='APPL' then HandleSpecialIcon(-3996)
  685.         else HandleSpecialIcon(-4000)
  686.     end;
  687.  
  688. {--------------------------------------------------------------------------
  689.     
  690.     CloseThePallette
  691.         If we've got a window, close it.  Note just one call to close the service window.
  692.         This should only be called from the 'real' application, not from the event handler.
  693.         
  694.  
  695.  --------------------------------------------------------------------------}
  696. Procedure CloseThePallette;
  697. var    io:OSErr;
  698. begin
  699.     if storage^.StoredPalletteWindow<>nil then begin
  700.         io:=CloseServiceWindow(storage^.StoredPalletteWindow);
  701.         storage^.StoredPalletteWindow:=nil;
  702.         end;
  703.     end;
  704.  
  705. {--------------------------------------------------------------------------
  706.     
  707.     DrawTheWindow
  708.         Just draw the window.  Note that the ServiceWindow is just a
  709.         window for this purpose.  Since we're calling this from our jGNE
  710.         Event Filter, we are NOT in our owner layer.  So, we don't have our
  711.         A5 world, and our resource file isn't open.  If this was a problem,
  712.         we could go through our IdleProc handler.
  713.         
  714.  
  715.  --------------------------------------------------------------------------}
  716. Procedure DrawTheWindow;
  717. var    thewindow:windowptr; therect:rect;
  718.     s2:str255;
  719.     io:OSErr;
  720.     index,thecount:integer;
  721.     thechar:char;
  722. begin
  723.     thewindow:=storage^.StoredPalletteWindow;
  724.     if thewindow<>nil then begin
  725.         beginupdate(thewindow);
  726.         setport(thewindow);
  727.         with storage^ do begin {Start getting the count of files}
  728.             if IAmZoomed then
  729.                 for index:=1 to PalletteIcons do begin
  730.                     s2:=TheName[index];
  731.                     therect:=thewindow^.portrect;
  732.                     with therect do begin
  733.                         left:=(index-1)*MyItemWidth;
  734.                         right:=left+MyItemWidth;
  735.                         PlotFileIcon(s2,PalletteVref,PalletteDirID,therect);
  736.                         {if index<11 then begin
  737.                             TextFont(0); TextSize(0);
  738.                             if index<10 then thechar:=chr(ord('0')+index)
  739.                                 else thechar:='0';
  740.                             moveto(left,top+32); drawchar(thechar);
  741.                             end;}
  742.                         top:=thewindow^.portrect.top+32;
  743.                         bottom:=thewindow^.portrect.bottom;
  744.                         TextFont(applFont);
  745.                         TextSize(9);
  746.                         TextBox(POINTER(ORD(@s2)+1),LENGTH(s2),therect,teJustCenter);
  747.                         end;
  748.                     end;
  749.             end;
  750.         endupdate(thewindow);
  751.         end;
  752.     end;
  753.  
  754. {--------------------------------------------------------------------------
  755.     
  756.     OpenPalletteWindow
  757.         Creates the window.  We find our icons to deal with, and thus
  758.         calculates the window's bounds.  Then, just create it by calling
  759.         NewServiceWindow with kCurrentProcess for the "component".  This means
  760.         that no component owns it.
  761.  
  762.  --------------------------------------------------------------------------}
  763. Function OpenPalletteWindow(TheSpec:FSSpec):OSErr;
  764. var    therect:rect;
  765.     thewindow:windowptr;
  766.     s2:str255;
  767.     index,thecount,NumIcons:integer;
  768.     myCPB:CInfoPBRec;
  769.     io:OSErr;
  770.         
  771.         Procedure cio(io:OSErr);
  772.         begin
  773.             if io<>NoErr then begin
  774.                 OpenPalletteWindow:=io;
  775.                 exit(OpenPalletteWindow);
  776.                 end;
  777.             end;
  778. begin
  779.    OpenPalletteWindow:=NoErr;
  780.    with mycpb,storage^ do begin {Get the DirID, and the number of files}
  781.         ioNamePtr:=@s2; s2:=TheSpec.name;
  782.         iovrefnum:=TheSpec.vrefnum;
  783.         ioDrDirID:=TheSpec.ParID;
  784.         ioFDirIndex:=0;
  785.         cio(PBGetCatInfo(@mycpb,false));
  786.         if BitTst(@ioFlAttrib,3)=false then cio(-100);
  787.         PalletteVref:=iovrefnum;
  788.         PalletteDirID:=ioDrDirID;
  789.         PalletteName:=TheSpec.name;
  790.         PalletteDTMan:=FSDTManRefNum(PalletteVref);
  791.         
  792.         NumIcons:=ioDrNmFls; {let's find the first 10 visible files/folders}
  793.         thecount:=0;
  794.         index:=1;
  795.         while (index<=NumIcons) and (thecount<MaxNumberIcons) do begin
  796.             ioNamePtr:=@s2; s2:='';
  797.             iovrefnum:=PalletteVref;
  798.             ioDrDirID:=PalletteDirID;
  799.             ioFDirIndex:=index;
  800.             io:=PBGetCatInfo(@mycpb,false);
  801.             if io=NoErr then
  802.                 if BitTst(@ioFlAttrib,3)=false then
  803.                     if bitand(ioFlFndrInfo.fdFlags,fInvisible)=0 then begin
  804.                         thecount:=thecount+1;
  805.                         TheName[thecount]:=s2;
  806.                         end;
  807.             index:=index+1;
  808.             end;
  809.         PalletteIcons:=thecount;
  810.         end;
  811.     if storage^.StoredPalletteWindow<>nil then CloseThePallette;
  812.     storage^.IAmZoomed:=true;
  813.     with therect do begin
  814.         bottom:=storage^.BottomLeft.v; left:=storage^.BottomLeft.h;
  815.         if (storage^.PalletteIcons>0) then begin
  816.             top:=bottom-MyItemHeight;
  817.             right:=left+(storage^.PalletteIcons*MyItemWidth);
  818.             end
  819.             else begin
  820.                 right:=left+150;
  821.                 top:=bottom-1;
  822.                 end;
  823.         end;
  824.     cio(NewServiceWindow(nil, therect,storage^.PalletteName,true,zoomNoGrow,pointer(-1),true,
  825.         componentInstance(kCurrentProcess),thewindow));
  826.     storage^.StoredPalletteWindow:=thewindow;
  827.     HiliteWindow(thewindow,true);
  828.     SavePrefs;
  829.     end;
  830.  
  831. {--------------------------------------------------------------------------
  832.     
  833.     ZoomThePallette
  834.         Flip from big window to little window
  835.  
  836.  --------------------------------------------------------------------------}
  837. Procedure ZoomThePallette;
  838. var    io:OSErr;
  839.     thewindow:windowptr;
  840.     therect:rect;
  841. begin
  842.     with storage^ do
  843.         if StoredPalletteWindow<>nil then begin
  844.             IAmZoomed:=not IAmZoomed;
  845.             io:=CloseServiceWindow(StoredPalletteWindow);
  846.             with therect do begin
  847.                 bottom:=storage^.BottomLeft.v; left:=storage^.BottomLeft.h;
  848.                 if (PalletteIcons>0) and (IAmZoomed) then begin
  849.                     top:=bottom-MyItemHeight;
  850.                     right:=left+(storage^.PalletteIcons*MyItemWidth);
  851.                     end
  852.                     else begin
  853.                         right:=left+150;
  854.                         top:=bottom-1;
  855.                         end;
  856.                 end;
  857.             io:=(NewServiceWindow(nil, therect,PalletteName,true,zoomNoGrow,pointer(-1),true,
  858.                 componentInstance(kCurrentProcess),thewindow));
  859.             StoredPalletteWindow:=thewindow;
  860.             HiliteWindow(thewindow,true);
  861.             end;
  862.     end;
  863.  
  864. {--------------------------------------------------------------------------
  865.     
  866.     SetWhatToDo
  867.         We don't want to do much from our jGNE Event Filter, because that lives
  868.         in other applications.  So, we set a flag for what to do, and call
  869.         WakeUpProcess to break us out of our long WaitNextEvent.
  870.  
  871.  --------------------------------------------------------------------------}
  872. Procedure SetWhatToDo(thecommand:integer);
  873. var    io:OSErr;
  874. begin
  875.     storage^.WhatToDo:=thecommand;
  876.     io:=WakeUpProcess(storage^.MyProcess);
  877.     end;
  878.  
  879. {--------------------------------------------------------------------------
  880.     
  881.     LayerIdleProc
  882.         Called from our app's main event loop, if there's a flag for a deferred
  883.         action, we handle it now.
  884.         
  885.         We've got a special handlers for quitting when the pallette is
  886.         closed.
  887.         
  888.         If one of our icons have been clicked on, we'll launch it here.  We
  889.         might have been able to do it from the frontmost app, but this is
  890.         safer.  Also, we know we're in an Apple Event aware app, so we can
  891.         send the AppleEvents cleanly.
  892.  
  893.  --------------------------------------------------------------------------}
  894. Procedure LayerIdleProc(var doneflag:boolean);
  895.     
  896.     Procedure HandleAction(which:integer);
  897.     var    io:OSErr;
  898.     begin
  899.         
  900.         with storage^ do begin {Send AppleEvent to Finder to open the file}
  901.             io:=TellFinderOpen(TheName[which],PalletteVref,PalletteDirID);
  902.             end;
  903.         end;
  904.     
  905. begin
  906.     case storage^.WhatToDo of
  907.         kClosePallette:doneFlag:=true; {Quit the pLayer}
  908.         kZoomPallette:ZoomThePallette;
  909.         otherwise 
  910.             if storage^.WhatToDo>0 then
  911.                 HandleAction(storage^.WhatToDo);
  912.         end;
  913.     storage^.WhatToDo:=0;
  914.     end;
  915.  
  916. {--------------------------------------------------------------------------
  917.     
  918.     myGNEFilter
  919.         This is how we see the events for our window.  It's called from assembler
  920.         glue to jGNEFilter (it's not a trap patching, though I'll admit it's a
  921.         technicallity).
  922.         
  923.         This code executes in the heap and A5 world of whatever the frontmost app
  924.         is, it is NOT likely to be running inside of pLayer.  So, globals should
  925.         be dealt with carefully if at all, and we need to be careful.
  926.         
  927.         We only handle click events.  We can hilite rectangles (but we MUST save and
  928.         restore the port, because it's not our port we're tromping over!) and use
  929.         normal window calls like TrackGoAway and DragWindow.
  930.         
  931.         To detect our clicks, we call a different kind of FindWindow that finds a
  932.         service window.  We then must make sure it's OUR service window (not all
  933.         service windows might be ours).
  934.         
  935.         Once we've handled our events, we must make sure to turn them into null events,
  936.         or they will be passed on to the operating system!
  937.         
  938.         We also check here to see if our window needs updating.  Service Windows
  939.         appear not to get update events, so we have to check manually.  (I could be
  940.         wrong on this, this is what I've discovered so far.)  My update routine doesn't
  941.         use any resources of mine, which is fortunate, because again I'm not really in
  942.         my application's layer.  If this was a problem, I could just flag that an updating
  943.         is necessary and handle it in my application's main event loop.
  944.         
  945.  --------------------------------------------------------------------------}
  946. Function myGNEFilter (result:integer; var event:EventRecord):integer;
  947. var    tempwindow:windowptr; typefind:integer;
  948.     Procedure KillEvent;
  949.     begin
  950.         event.what:=nullEvent;
  951.         end;
  952.     
  953.     Procedure HandleDrag;
  954.     var    tempport:Grafptr;
  955.         dragrect:rect;
  956.     begin
  957.         SetRect(dragRect,-32767,-32767,32767,32767);
  958.         DragWindow(tempWindow,event.where,dragRect);
  959.         Getport(tempport);
  960.         Setport(tempwindow);
  961.         with storage^.BottomLeft do begin
  962.             h:=tempwindow^.portrect.left;
  963.             v:=tempwindow^.portrect.bottom;
  964.             end;
  965.         LocalToGlobal(storage^.BottomLeft);
  966.         Setport(tempport);
  967.         KillEvent;
  968.         SavePrefs;
  969.         end;
  970.     
  971.     Procedure HandleClick;
  972.     var    tempport:Grafptr;
  973.         ThePoint:point;
  974.         AmIn:Boolean;
  975.         TheRect:rect;
  976.         WhichItem:integer;
  977.     begin
  978.         KillEvent;
  979.         Getport(tempport);
  980.         Setport(tempwindow);
  981.         with storage^ do 
  982.             if IAmZoomed then begin
  983.                 ThePoint:=event.where;
  984.                 GlobalToLocal(ThePoint);
  985.                 WhichItem:=(ThePoint.h-tempwindow^.portrect.left) div MyItemWidth+1;
  986.                 if (WhichItem>0) and (WhichItem<=PalletteIcons) then begin
  987.                     TheRect:=tempWindow^.portrect;
  988.                     with TheRect do begin
  989.                         left:=(WhichItem-1)*MyItemWidth;
  990.                         right:=left+MyItemWidth;
  991.                         end;
  992.                     BitClr(pointer(HILITEMODE),0);
  993.                     InvertRect(TheRect);
  994.                     AmIn:=true;
  995.                     While WaitMouseUp do begin
  996.                         GetMouse(ThePoint);
  997.                         if PtInRect(ThePoint,TheRect)<>AmIn then begin
  998.                             AmIn:=not AmIn;
  999.                             BitClr(pointer(HILITEMODE),0);
  1000.                             InvertRect(TheRect);
  1001.                             end;
  1002.                         end;
  1003.                     if AmIn then begin
  1004.                         BitClr(pointer(HILITEMODE),0);
  1005.                         InvertRect(TheRect);
  1006.                         SetWhatToDo(WhichItem);
  1007.                         end;
  1008.                     end;
  1009.                 end;
  1010.         SetPort(tempport);
  1011.         end;
  1012. begin
  1013.     if storage^.StoredPalletteWindow<>nil then
  1014.         case event.what of
  1015.             mouseDown:begin
  1016.                 typefind:=FindServiceWindow(event.where,tempWindow);
  1017.                 if typefind>inSysWindow then
  1018.                     if tempwindow=storage^.StoredPalletteWindow then begin
  1019.                         case typefind of
  1020.                             inDrag: HandleDrag; 
  1021.                             inGoAway: begin
  1022.                                 IF TrackGoAway(tempWindow,event.where) THEN
  1023.                                     SetWhatToDo(kClosePallette);
  1024.                                 KillEvent;
  1025.                                 end;
  1026.                             inZoomIn,inZoomOut: begin
  1027.                                 if TrackBox(tempWindow,event.where,typeFind) then
  1028.                                     SetWhatToDo(kZoomPallette);
  1029.                                 KillEvent;
  1030.                                 end;
  1031.                             inContent: HandleClick;
  1032.                             END;
  1033.                         end;
  1034.                 end;
  1035.             
  1036.             nullEvent: begin
  1037.                 tempwindow:=storage^.StoredPalletteWindow;
  1038.                 if tempwindow<>nil then
  1039.                     if not EmptyRgn(windowpeek(tempwindow)^.updateRgn) then DrawTheWindow;
  1040.                 end;
  1041.             END;    { of event case }
  1042.     myGNEFilter:=result;
  1043.     end;
  1044.  
  1045. {--------------------------------------------------------------------------
  1046.     
  1047.     CloseLayer
  1048.         This is called right before quitting.  We MUST close the pallette, if
  1049.         we don't, it'll stay around forever and be very annoying.  We also have
  1050.         to unhook ourselves from jGNEFilter.  Yes, we could encounter problems if
  1051.         someone has hooked jGNEFilter after we did.  I don't have a solution for
  1052.         that.
  1053.         
  1054.  --------------------------------------------------------------------------}
  1055. Procedure CloseLayer;
  1056. begin
  1057.     CloseThePallette;
  1058.     UnHook;
  1059.     end;
  1060.     
  1061. {--------------------------------------------------------------------------
  1062.     
  1063.     InitLayer
  1064.         This is called from our setup code to draw the window.  We check to
  1065.         make sure that we have the Text Services Manager here, and remember our
  1066.         process serial number (so we can call WakeUpProcesson ourself).  Finally,
  1067.         we hook ourselves into jGNEFilter so that we can get the events for our
  1068.         pallette.
  1069.         
  1070.  --------------------------------------------------------------------------}
  1071. Function InitLayer:OSErr;
  1072. var    io:OSErr;
  1073.     theresult:longint;
  1074. begin
  1075.     storage^.WhatToDo:=0;
  1076.     InitLayer:=-1;
  1077.     if gestalt(gestaltTSMgrVersion,theresult)<>NoErr then exit(InitLayer);
  1078.     io:=GetCurrentProcess(storage^.MyProcess);
  1079.     
  1080.     with storage^.BottomLeft do begin
  1081.         v:=screenbits.bounds.bottom-10;
  1082.         h:=screenbits.bounds.left+20;
  1083.         end;
  1084.  
  1085.     if io=NoErr then HookUp;
  1086.     InitLayer:=io;
  1087.     end;
  1088.  
  1089. {--------------------------------------------------------------------------
  1090.     
  1091.     HandleNew
  1092.         Have the user select a folder, and if found, open the pallette to it.
  1093.         
  1094.  --------------------------------------------------------------------------}
  1095. Procedure HandleNew;
  1096. var    TheSpec:FSSpec;    io:OSErr;
  1097. begin
  1098.     if GetAFolder(TheSpec) then io:=OpenPalletteWindow(TheSpec);
  1099.     end;
  1100.  
  1101. {--------------------------------------------------------------------------
  1102.     
  1103.     HandleSave;
  1104.         Save a reference to this pallette
  1105.         
  1106.  --------------------------------------------------------------------------}
  1107. Procedure HandleSave;
  1108. VAR MyReply:StandardFileReply;
  1109.     io:OSErr;
  1110.  
  1111. begin
  1112.     StandardPutFile('Save Pallette reference as:','',MyReply);
  1113.     if MyReply.sfgood then begin
  1114.         io:=SaveThePallette(MyReply.sfFile);
  1115.         end;
  1116.     end;
  1117.  
  1118. {--------------------------------------------------------------------------
  1119.     
  1120.     HandleOpen;
  1121.         Open a previously saved reference
  1122.         
  1123.  --------------------------------------------------------------------------}
  1124. Procedure HandleOpen;
  1125. VAR MyReply:StandardFileReply;
  1126.     MyFile2:SFTypeList;
  1127.     io:OSErr;
  1128.  
  1129. begin
  1130.     MyFile2[0]:='pall';
  1131.     StandardGetFile(nil,1,MyFile2,MyReply);
  1132.     if MyReply.sfgood then begin
  1133.         io:=ReadThePallette(MyReply.sfFile);
  1134.         if io=NoErr then io:=OpenPalletteWindow(MyReply.sfFile);
  1135.         end;
  1136.     end;
  1137.  
  1138. {--------------------------------------------------------------------------
  1139.     
  1140.     DoOpenFile;
  1141.         In Response to an AppleEvent, open the (first) file passed)
  1142.         
  1143.  --------------------------------------------------------------------------}
  1144. Procedure DoOpenFile(TheSpec:FSSpec);
  1145. var    io:OSErr;
  1146. begin
  1147.     io:=ReadThePallette(TheSpec);
  1148.     if io=NoErr then io:=OpenPalletteWindow(TheSpec);
  1149.     end;
  1150.  
  1151. {--------------------------------------------------------------------------
  1152.     
  1153.     DoOpenApp;
  1154.         In Response to an AppleEvent, open the prefs folder.  If no such
  1155.         luck, select the folder.
  1156.         
  1157.  --------------------------------------------------------------------------}
  1158. Procedure DoOpenApp(AllowUserInteraction:Boolean);
  1159. var    TheSpec:FSSpec;
  1160.     io:OSErr;
  1161. begin
  1162.     {Try to open our Prefs folder}
  1163.     GetPrefsFileSpec(TheSpec);
  1164.     io:=ReadThePallette(TheSpec);
  1165.     if io=NoErr then io:=OpenPalletteWindow(TheSpec);
  1166.     
  1167.     if (io<>NoErr) and AllowUserInteraction then HandleNew;
  1168.     
  1169.     end;
  1170.  
  1171. END.
  1172.